﻿using psafth.AMB;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace psafth.P3Decoder
{
    class Program
    {
        static string status = "8e 02 33 00 0d 8d ad 00 00 01 00 01 04 57 34 00 00 03 04 08 8a 29 00 04 08 58 d4 23 9d 96 db 04 00 05 02 5c 00 06 02 80 00 08 02 00 00 81 04 be 13 04 00 8f";
        static byte[] statusBytes = new byte[] { 0x8e, 0x02, 0x1f, 0x00, 0x76, 0xc4, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x2b, 0x00, 0x07, 0x02, 0x20, 0x00, 0x0c, 0x01, 0x77, 0x06, 0x01, 0x00, 0x81, 0x04, 0xbe, 0x13, 0x04, 0x00, 0x8f };
        static byte[] passingFirst = new byte[] { 0x8e, 0x02, 0x33, 0x00, 0xeb, 0x1d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x04, 0x9d, 0x09, 0x00, 0x00, 0x03, 0x04 };
        static byte[] passingSecond = new byte[] { 0x04, 0x08 };
        static byte[] passingThird = new byte[] { 0x05, 0x02, 0x5f, 0x00, 0x06, 0x02, 0x2e, 0x00, 0x08, 0x02, 0x00, 0x00, 0x81, 0x04, 0xbe, 0x13, 0x04, 0x00, 0x8f };

        public static byte[] ToSend
        {
            get;
            set;
        }

        static void Main(string[] args)
        {
            Console.Title = "RC3Decoder";
            BackgroundWorker _bw = new BackgroundWorker();

            _bw.DoWork += _bw_DoWork;
            _bw.ProgressChanged += _bw_ProgressChanged;

            _bw.RunWorkerAsync();

            while (!_bw.CancellationPending || _bw.IsBusy)
            {

            }
        }

        static void _bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            DateTime start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(-3);
            //return epoch.AddMilliseconds(unixTime / 1000);

            TimeSpan epoch = DateTime.Now.Subtract(start);

            byte[] transponderId = (byte[])e.UserState;

            byte[] time = BitConverter.GetBytes(epoch.TotalMilliseconds / 1000);

            byte[] passingBytes = new byte[passingFirst.Length + time.Length + passingSecond.Length + transponderId.Length + passingThird.Length];
            System.Buffer.BlockCopy(passingFirst, 0, passingBytes, 0, passingFirst.Length);
            System.Buffer.BlockCopy(transponderId, 0, passingBytes, passingFirst.Length, transponderId.Length);
            System.Buffer.BlockCopy(passingSecond, 0, passingBytes, passingFirst.Length + transponderId.Length, passingSecond.Length);
            System.Buffer.BlockCopy(time, 0, passingBytes, passingFirst.Length + passingSecond.Length + transponderId.Length, time.Length);
            System.Buffer.BlockCopy(passingThird, 0, passingBytes, passingFirst.Length + passingSecond.Length + transponderId.Length + time.Length, passingThird.Length);


            // Calculate and insert CRC
            byte[] tmpBytesCRC = AMBCalculator.InsertCRC(passingBytes);

            // Escape
            byte[] escapedBytes = AMBCalculator.Escape(tmpBytesCRC);

            Console.WriteLine(BitConverter.ToInt32(transponderId, 0));

            ToSend = passingBytes;
        }



        private static void _bw_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            while (true)
            {
                //try
                //{
                // Create a TcpClient.
                // Note, for this client to work you need to have a TcpServer
                // connected to the same address as specified by the server, port
                // combination

                TcpListener server = new TcpListener(IPAddress.Any, 5403);

                server.Stop();

                server.Start();

                //try
                //{
                BackgroundWorker fredrik = new TransponderPassing() { TransponderId = 4777687 };
                BackgroundWorker johan = new TransponderPassing() { TransponderId = 3581439 };
                BackgroundWorker per = new TransponderPassing() { TransponderId = 9075509 };
                BackgroundWorker marth = new TransponderPassing() { TransponderId = 9530045 };
                BackgroundWorker daniel = new TransponderPassing() { TransponderId = 8929082 };
                BackgroundWorker anders = new TransponderPassing() { TransponderId = 4917087 };
                BackgroundWorker fredrick = new TransponderPassing() { TransponderId = 6006846 };
                BackgroundWorker staffan = new TransponderPassing() { TransponderId = 9221969 };
                BackgroundWorker peter = new TransponderPassing() { TransponderId = 9796583 };
                BackgroundWorker magnus = new TransponderPassing() { TransponderId = 9454387 };
                BackgroundWorker lennart = new TransponderPassing() { TransponderId = 5487897 };
                BackgroundWorker sven = new TransponderPassing() { TransponderId = 3056340 };
                BackgroundWorker stefan = new TransponderPassing() { TransponderId = 6641950 };
                BackgroundWorker unknown = new TransponderPassing() { TransponderId = 7654321 };


                fredrik.ProgressChanged += _bw_ProgressChanged;
                johan.ProgressChanged += _bw_ProgressChanged;
                per.ProgressChanged += _bw_ProgressChanged;
                daniel.ProgressChanged += _bw_ProgressChanged;
                anders.ProgressChanged += _bw_ProgressChanged;
                fredrick.ProgressChanged += _bw_ProgressChanged;
                marth.ProgressChanged += _bw_ProgressChanged;
                peter.ProgressChanged += _bw_ProgressChanged;
                magnus.ProgressChanged += _bw_ProgressChanged;
                lennart.ProgressChanged += _bw_ProgressChanged;
                unknown.ProgressChanged += _bw_ProgressChanged;
                sven.ProgressChanged += _bw_ProgressChanged;
                stefan.ProgressChanged += _bw_ProgressChanged;

                fredrik.WorkerReportsProgress = true;
                johan.WorkerReportsProgress = true;
                per.WorkerReportsProgress = true;
                daniel.WorkerReportsProgress = true;
                anders.WorkerReportsProgress = true;
                fredrick.WorkerReportsProgress = true;
                marth.WorkerReportsProgress = true;
                peter.WorkerReportsProgress = true;
                magnus.WorkerReportsProgress = true;
                unknown.WorkerReportsProgress = true;
                lennart.WorkerReportsProgress = true;
                sven.WorkerReportsProgress = true;
                stefan.WorkerReportsProgress = true;

                TcpClient client = server.AcceptTcpClient(); // Get client connection

                client.ReceiveTimeout = 15000;
                client.SendTimeout = 15000;

                fredrik.RunWorkerAsync();
                Thread.Sleep(100);
                johan.RunWorkerAsync();
                Thread.Sleep(100);
                per.RunWorkerAsync();
                Thread.Sleep(100);
                daniel.RunWorkerAsync();
                Thread.Sleep(100);
                anders.RunWorkerAsync();
                Thread.Sleep(100);
                fredrick.RunWorkerAsync();
                Thread.Sleep(100);
                marth.RunWorkerAsync();
                Thread.Sleep(100);
                peter.RunWorkerAsync();
                Thread.Sleep(100);
                magnus.RunWorkerAsync();
                Thread.Sleep(100);
                lennart.RunWorkerAsync();
                Thread.Sleep(100);
                sven.RunWorkerAsync();
                //Thread.Sleep(100);
                //stefan.RunWorkerAsync();

                Thread.Sleep(100);
                unknown.RunWorkerAsync();
                

                NetworkStream netStream = client.GetStream();

                netStream.ReadTimeout = 15000;
                netStream.WriteTimeout = 15000;

                while (client.Connected)
                {
                    netStream.Write(statusBytes, 0, statusBytes.Length);
                    netStream.Flush();

                    break;
                }

                while (client.Connected)
                {
                    if (ToSend != null)
                    {
                        if (netStream.CanWrite)
                        {
                            try
                            {
                                netStream.Write(ToSend, 0, ToSend.Length);
                                netStream.Flush();

                                netStream.Write(statusBytes, 0, statusBytes.Length);
                                netStream.Flush();

                                ToSend = null;
                            }
                            catch (Exception ex)
                            {
                                //client = server.AcceptTcpClient();
                                //netStream = client.GetStream();
                            }
                        }
                    }
                }
            }
        }
    }
}
